package com.wing.oauth2.details.clientdetails;

import com.google.common.collect.Sets;
import com.wing.common.utils.JsonResult;
import com.wing.user.feign.UserClient;
import com.wing.user.model.response.ClientVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.ClientRegistrationException;
import org.springframework.security.oauth2.provider.client.BaseClientDetails;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;

/**
 * OAuth2 客户端信息
 *
 * @author
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ClientDetailsServiceImpl implements ClientDetailsService {

    private final UserClient userClient;

    private static final String SEPARATOR = ",";

    /**
     * Load a client by the client id. This method must not return null.
     *
     * @param clientId The client id.
     * @return The client details (never null).
     * @throws ClientRegistrationException If the client account is locked, expired, disabled, or invalid for any other reason.
     */
    @Override
    public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException {
        log.info("--------------loadClientByClientId start--------------");
        log.info("--------------clientId:"+clientId+"--------------");
        JsonResult<ClientVO> clientResult = userClient.findClientByClientId(clientId);
        if (clientResult == null || clientResult.getData() == null) {
            throw new ClientRegistrationException("client not found");
        }
        log.info("--------------loadClientByClientId end--------------");
        return this.buildBaseClientDetails(clientResult.getData());
    }

    /**
     * 构建ClientDetails
     *
     * @param sysClient 系统客户端
     * @return ClientDetails
     */
    private ClientDetails buildBaseClientDetails(ClientVO sysClient) {
        BaseClientDetails baseClientDetails = new BaseClientDetails();
        baseClientDetails.setClientId(sysClient.getClientId());
        baseClientDetails.setAutoApproveScopes(new ArrayList<>());
        String autoApproveScopes = sysClient.getAutoApproveScopes();
        if (StringUtils.isNotBlank(autoApproveScopes)) {
            String[] split = StringUtils.split(autoApproveScopes, SEPARATOR);
            baseClientDetails.setAutoApproveScopes(Arrays.asList(split));
        }
        baseClientDetails.setClientSecret(sysClient.getClientSecret());
        baseClientDetails.setScope(new ArrayList<>());
        String scopes = sysClient.getScopes();
        if (StringUtils.isNotBlank(scopes)) {
            String[] split = StringUtils.split(scopes, SEPARATOR);
            baseClientDetails.setScope(Arrays.asList(split));
        }
        String resourceIds = sysClient.getResourceIds();
        baseClientDetails.setResourceIds(new ArrayList<>());
        if (StringUtils.isNotBlank(resourceIds)) {
            String[] split = StringUtils.split(resourceIds, SEPARATOR);
            baseClientDetails.setResourceIds(Arrays.asList(split));
        }
        String grantTypes = sysClient.getGrantTypes();
        if (StringUtils.isNotBlank(grantTypes)) {
            String[] split = StringUtils.split(grantTypes, SEPARATOR);
            baseClientDetails.setAuthorizedGrantTypes(Arrays.asList(split));
        }
        String redirectUris = sysClient.getRedirectUris();
        baseClientDetails.setRegisteredRedirectUri(Sets.newHashSet());
        if (StringUtils.isNotBlank(redirectUris)) {
            String[] split = StringUtils.split(redirectUris, SEPARATOR);
            baseClientDetails.setRegisteredRedirectUri(Sets.newHashSet(split));
        }
        String authorityIds = sysClient.getAuthorityIds();
        baseClientDetails.setAuthorities(new ArrayList<>());
        if (StringUtils.isNotBlank(authorityIds)) {
            // JsonResult<Collection<AuthorityVO>> sysAuthorityListResult = userClient.authorityList(authorityIds);
            // baseClientDetails.setAuthorities(sysAuthorityListResult.getData());
        }
        baseClientDetails.setAccessTokenValiditySeconds(Math.toIntExact(sysClient.getAccessTokenValiditySeconds()));
        baseClientDetails.setRefreshTokenValiditySeconds(Math.toIntExact(sysClient.getRefreshTokenValiditySeconds()));
        // 附加信息
        // baseClientDetails.setAdditionalInformation();
        return baseClientDetails;
    }

}
